#include "arreglo_redimensionable.h"
#include <iostream>
#include <sstream> // define el tipo ostringstream
#include <cassert> // define assert
using namespace std;

template <typename T>
void asegurar(const Arreglo_redimensionable<T>& a, string s){
    ostringstream out;
    a.mostrar(out);
    string t = out.str();
    if(s != t){
        cerr << s << " != " << t << endl;
        assert(false);
    }
}

#define RUNTEST(t){ cerr << "Corriendo test " << #t << endl; t (); cerr << "Terminado test " << #t << endl; }

void testTam(){
    Arreglo_redimensionable<int> a;
    Arreglo_redimensionable< Arreglo_redimensionable<int> > aa;
    for(int i=0;i<5;i++){
        a.extender();
        aa.extender();
        assert(a.tam()==(i+1));
        assert(aa.tam()==(i+1));
    }
    for(int i=0;i<5;i++){
        a.agregar(i,i);
        aa.agregar(a,i);
        assert(a.tam()==5);
        assert(aa.tam()==5);
    }
    Arreglo_redimensionable<int> b;
    Arreglo_redimensionable< Arreglo_redimensionable<int> > bb;
    for(int i=0;i<5;i++){
        b.extender();
        bb.extender();
        b.agregar(i,i);
        bb.agregar(b,i);
        assert(b.tam()==(i+1));
        assert(bb.tam()==(i+1));
    }
}

void testAgregar(){
    Arreglo_redimensionable<int> a;
    Arreglo_redimensionable< Arreglo_redimensionable<int> > aa;
    a.extender();
    a.extender();
    aa.extender();
    aa.extender();
    a.agregar(0,0);
    aa.agregar(a,0);
    asegurar(a,"[0]");
    asegurar(aa,"[[0]]");
    a.agregar(1,1);
    aa.agregar(a,1);
    asegurar(a,"[0,1]");
    asegurar(aa,"[[0],[0,1]]");
    a.extender();
    a.agregar(2,2);
    aa.extender();
    aa.agregar(a,2);
    asegurar(a,"[0,1,2]");
    asegurar(aa,"[[0],[0,1],[0,1,2]]");
    a.extender();
    a.agregar(3,3);
    aa.extender();
    aa.agregar(a,3);
    asegurar(a,"[0,1,2,3]");
    asegurar(aa,"[[0],[0,1],[0,1,2],[0,1,2,3]]");
}

void testDefinido(){
    Arreglo_redimensionable<int> a;
    Arreglo_redimensionable< Arreglo_redimensionable<int> > aa;
    a.extender();
    aa.extender();
    assert(a.definido(0)==false);
    assert(aa.definido(0)==false);
    a.agregar(5,0);
    aa.agregar(a,0);
    assert(a.definido(0)==true);
    assert(aa.definido(0)==true);
}

void testIesimo(){
    Arreglo_redimensionable<int> a;
    Arreglo_redimensionable< Arreglo_redimensionable<int> > aa;
    for(int i=0;i<5;i++){
        a.extender();
        a.agregar(i,i);
        aa.extender();
        aa.agregar(a,i);
        assert(a.iesimo(i)==i);
        assert(aa.iesimo(i)==a);
    }
}

void testExtender(){
    Arreglo_redimensionable<int> a;
    Arreglo_redimensionable< Arreglo_redimensionable<int> > aa;
    for(int i=0;i<5;i++){
        a.extender();
        aa.extender();
        asegurar(a,"[]");
        asegurar(aa,"[]");
    }
}

int main(){
    RUNTEST(testTam);
    RUNTEST(testAgregar);
    RUNTEST(testDefinido);
    RUNTEST(testIesimo);
    RUNTEST(testExtender);
	return 0;
}
